#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
#![feature(future_join)]

extern crate core;

pub use crate::ch1::*;
pub use crate::ch2::*;
pub use crate::ch3::*;
pub use crate::ch4::*;

pub mod my_mod {
    fn private_function() {
        println!("called my_mod::private_function()");
    }

    pub fn function() {
        println!("called my_mod::function()");
    }

    pub fn indirect_access() {
        println!("called my_mod::indirect_access(), that\n> ");
        private_function();
    }

    pub mod nested {
        pub fn function() {
            println!("called my_mod::nested::function()");
        }

        #[allow(dead_code)]
        fn private_function() {
            println!("called my_mod::nested::private_function()");
        }

        pub(in crate::my_mod) fn public_function_in_my_mod() {
            println!("called my_mod::nested::public_function_in_my_mod()");
            public_function_in_nested();
        }

        pub(self) fn public_function_in_nested() {
            println!("called my_mod::nested::public_function_in_nested()");
        }

        pub(super) fn public_function_in_super_mod() {
            println!("called my_mod::nested::public_function_in_super_mod()");
        }
    }

    pub fn call_public_function_in_my_mod() {
        println!("called my_mod::call_public_function_in_my_mod(), that\n> ");
        nested::public_function_in_my_mod();
        nested::public_function_in_super_mod();
        public_function_in_crate();
    }

    pub(crate) fn public_function_in_crate() {
        println!("called my_mod::public_function_in_crate()");
    }

    mod private_nested {
        #[allow(dead_code)]
        pub fn function() {
            println!("called my_mod::private_nested::function()");
        }
    }
}

fn function() {
    println!("called function()");
}

pub fn main() {
    crate::my_mod::function();
    my_mod::function();

    my_mod::indirect_access();
    my_mod::nested::function();
    my_mod::call_public_function_in_my_mod();

    my_mod::public_function_in_crate();
}

pub mod ch1;

pub mod ch2;

pub mod ch3;

pub mod ch4;

pub mod ch5;

pub mod ch6;

pub mod ch7;

pub fn gen_title(title: &str, level: usize) {
    return println!("{:-^width$}", title, width = level * 2);
}
